
/**
 *  \file rfcomm_internal.h
 *
 *  Module Internal Header File for RFCOMM. This header file contains the
 *  Data Structures, Type Definitions, and Function Declarations used
 *  internally in the RFCOMM module.
 */

/*
 *  Copyright (C) 2013. Mindtree Ltd.
 *  All rights reserved.
 */

#ifndef _H_RFCOMM_INTERNAL_
#define _H_RFCOMM_INTERNAL_

/* --------------------------------------------- Header File Inclusion */
#include "BT_common.h"
#include "BT_bottom_half.h"

#include "BT_rfcomm_api.h"
#include "rfcomm_support.h"
#include "rfcomm.h"

#include "l2cap.h"
#include "sm.h"


/* --------------------------------------------- RFCOMM Module Debug */
#ifndef RFCOMM_NO_DEBUG
#define RFCOMM_ERR(...)         BT_debug_error(BT_MODULE_ID_RFCOMM, __VA_ARGS__)
#else  /* RFCOMM_NO_DEBUG */
#define RFCOMM_ERR              BT_debug_null
#endif /* RFCOMM_NO_DEBUG */

#ifdef RFCOMM_DEBUG

#define RFCOMM_TRC(...)         BT_debug_trace(BT_MODULE_ID_RFCOMM, __VA_ARGS__)
#define RFCOMM_INF(...)         BT_debug_info(BT_MODULE_ID_RFCOMM, __VA_ARGS__)

#define RFCOMM_debug_dump_bytes(data, datalen) BT_debug_dump_bytes(BT_MODULE_ID_RFCOMM, (data), (datalen))

#else  /* RFCOMM_DEBUG */

#define RFCOMM_TRC              BT_debug_null
#define RFCOMM_INF              BT_debug_null

#define RFCOMM_debug_dump_bytes(data, datalen)

#endif /* RFCOMM_DEBUG */


/* --------------------------------------------- Global Definitions */

/* RFCOMM Server Channel - Minimum & Maximum Allowed Values */
#define RFCOMM_SERVER_CHANNEL_MIN               1
#define RFCOMM_SERVER_CHANNEL_MAX               30

/* DLCI Value for RFCOMM Session (0x00) */
#define RFCOMM_SESSION_DLCI                     0x00

/* RFCOMM DLCI State Values */
#define RFCOMM_DLCI_NONEXISTENT                 0x00
#define RFCOMM_DLCI_DISCONNECTED                0x01
#define RFCOMM_DLCI_CONNECTED                   0x02
#define RFCOMM_DLCI_IN_DISCONNECTION            0x03
#define RFCOMM_DLCI_IN_CONNECTION               0x04
#define RFCOMM_DLCI_IN_L2CAP_CONFIG             0x11
#define RFCOMM_DLCI_IN_L2CAP_CONNECT            0x12
#define RFCOMM_DLCI_IN_L2CAP_DISCONNECT         0x13

/* RFCOMM Session State Values */
#define RFCOMM_SESSION_INVALID                  RFCOMM_DLCI_NONEXISTENT

/* L2CAP Config States */
#define RFCOMM_L2CAP_CONFIG_NONE                0x00
#define RFCOMM_L2CAP_CONFIG_SELF                0x01
#define RFCOMM_L2CAP_CONFIG_PEER                0x02
#define RFCOMM_L2CAP_CONFIG_BOTH                0x03
#define RFCOMM_L2CAP_CONFIG_SELF_STARTED        0x04

/* RFCOMM Aggregate Flow Control Switched On/Off */
#define RFCOMM_AGGREGATE_FLOW_OFF               0x01
#define RFCOMM_AGGREGATE_FLOW_ON                0x00

/* RFCOMM Per DLCI Flow Control Switched On/Off */
#define RFCOMM_PER_DLCI_FLOW_OFF                0x01
#define RFCOMM_PER_DLCI_FLOW_ON                 0x00

/* RFCOMM CBFC Requested/Responded from/by Peer */
#define RFCOMM_CBFC_REQUESTED                   0x0F
#define RFCOMM_CBFC_RESPONDED                   0x0E

/* RFCOMM Initial Local Credit */
#define RFCOMM_INITIAL_LOCAL_CREDIT             0

/* RFCOMM CBFC Enabled/Disabled for a DLCI */
#define RFCOMM_CBFC_DISABLED                    0x00
#define RFCOMM_CBFC_ENABLED                     0x01

/*
 *  Length of RFCOMM UIH Packet containing Credits:
 *      Address - 1 Byte
 *      Control - 1 Byte
 *      Length  - 1 Byte (should have value of 1)
 *      Credits - 1 Byte
 *      FCS     - 1 Byte
 *
 *  Total = 5 Bytes.
 */
#define RFCOMM_UIH_CREDIT_LENGTH                5

/* RFCOMM Acknowledgement Timeout Value */
#define RFCOMM_ACK_TIMEOUT_VALUE                60

/* RFCOMM Default Frame Size for a DLCI */
#define RFCOMM_DEFAULT_FRAME_SIZE               127

/* L2CAP CID Value when RFCOMM Session is NOT used */
#define RFCOMM_L2CAP_CID_NULL                   0x0000

/*
 *  RFCOMM Mode Settings Commands/Responses Types
 *
 *  Bit Number      7  6  5  4  3  2  1  0
 *  ----------      -  -  -  -  -  -  -  -
 *  SABM         -  0  0  1 PF  1  1  1  1
 *  UA           -  0  1  1 PF  0  0  1  1
 *  DISC         -  0  1  0 PF  0  0  1  1
 *  DM           -  0  0  0 PF  1  1  1  1
 */
#define RFCOMM_SABM_COMMAND                     0x3F
#define RFCOMM_DISC_COMMAND                     0x53
#define RFCOMM_UA_RESPONSE                      0x73
#define RFCOMM_DM_RESPONSE_F_SET                0x1F
#define RFCOMM_DM_RESPONSE_F_RESET              0x0F
#define RFCOMM_UIH_P_SET                        0xFF
#define RFCOMM_UIH_P_RESET                      0xEF

/* RFCOMM Mode Setting Command/Response Packet Sizes */
#define RFCOMM_MODE_FRAME_SIZE                  4
#define RFCOMM_SABM_SIZE                        4
#define RFCOMM_DISC_SIZE                        4
#define RFCOMM_UA_SIZE                          4
#define RFCOMM_DM_SIZE                          4

/*
 *  RFCOMM Multiplexer Command/Response Types
 *
 *  Bit Number      7  6  5  4  3  2  1  0
 *  ----------      -  -  -  -  -  -  -  -
 *  PN           -  1  0  0  0  0  0 EA CR
 *  TEST         -  0  0  1  0  0  0 EA CR
 *  FCon         -  1  0  1  0  0  0 EA CR
 *  FCoff        -  0  1  1  0  0  0 EA CR
 *  MSC          -  1  1  1  0  0  0 EA CR
 *  NSC          -  0  0  0  1  0  0 EA CR
 *  RPN          -  1  0  0  1  0  0 EA CR
 *  RLS          -  0  1  0  1  0  0 EA CR
 */
#define RFCOMM_PN_COMMAND                       0x20
#define RFCOMM_TEST_COMMAND                     0x08
#define RFCOMM_FCON_COMMAND                     0x28
#define RFCOMM_FCOFF_COMMAND                    0x18
#define RFCOMM_MSC_COMMAND                      0x38
#define RFCOMM_NSC_COMMAND                      0x04
#define RFCOMM_RPN_COMMAND                      0x24
#define RFCOMM_RLS_COMMAND                      0x14

/* RFCOMM Multiplexer Command/Response Frame Sizes */
#define RFCOMM_PN_FRAME_SIZE                    10
#define RFCOMM_FC_ON_OFF_FRAME_SIZE             2
#define RFCOMM_FCON_FRAME_SIZE                  2
#define RFCOMM_FCOFF_FRAME_SIZE                 2
#define RFCOMM_NSC_FRAME_SIZE                   3
#define RFCOMM_RLS_FRAME_SIZE                   4
#define RFCOMM_RPN_FRAME_SIZE_1                 3
#define RFCOMM_RPN_FRAME_SIZE_8                 10
#define RFCOMM_MSC_FRAME_SIZE_2                 4
#define RFCOMM_MSC_FRAME_SIZE_3                 5

/* RFCOMM Multiplexer Command/Response Value Sizes */
#define RFCOMM_PN_VALUE_SIZE                    8
#define RFCOMM_FC_ON_OFF_VALUE_SIZE             0
#define RFCOMM_FCON_VALUE_SIZE                  0
#define RFCOMM_FCOFF_VALUE_SIZE                 0
#define RFCOMM_NSC_VALUE_SIZE                   1
#define RFCOMM_RLS_VALUE_SIZE                   2
#define RFCOMM_RPN_VALUE_SIZE_1                 1
#define RFCOMM_RPN_VALUE_SIZE_8                 8
#define RFCOMM_MSC_VALUE_SIZE_2                 2
#define RFCOMM_MSC_VALUE_SIZE_3                 3

#define RFCOMM_PN_FRAME_LENGTH                  (RFCOMM_PN_VALUE_SIZE + 2)
#define RFCOMM_RPN_REQUEST_FRAME_LENGTH         (RFCOMM_RPN_VALUE_SIZE_1 + 2)
#define RFCOMM_RPN_COMMAND_FRAME_LENGTH         (RFCOMM_RPN_VALUE_SIZE_8 + 2)
#define RFCOMM_MSC_VALUE_2_FRAME_LENGTH         (RFCOMM_MSC_VALUE_SIZE_2 + 2)
#define RFCOMM_MSC_VALUE_3_FRAME_LENGTH         (RFCOMM_MSC_VALUE_SIZE_3 + 2)
#define RFCOMM_RLS_FRAME_LENGTH                 (RFCOMM_RLS_VALUE_SIZE + 2)

/* RFCOMM Multiplexer Command/Response Length Bytes */
#define RFCOMM_PN_VALUE_LENGTH_BYTE             0x11
#define RFCOMM_FC_ON_OFF_VALUE_LENGTH_BYTE      0x01
#define RFCOMM_NSC_VALUE_LENGTH_BYTE            0x03
#define RFCOMM_RLS_VALUE_LENGTH_BYTE            0x05
#define RFCOMM_RPN_VALUE_1_LENGTH_BYTE          0x03
#define RFCOMM_RPN_VALUE_8_LENGTH_BYTE          0x11
#define RFCOMM_MSC_VALUE_2_LENGTH_BYTE          0x05
#define RFCOMM_MSC_VALUE_3_LENGTH_BYTE          0x07

/* RFCOMM Parameter Negotiation - Acknowledgment Timeout */
#define RFCOMM_PN_ACK_TIMEOUT                   0x00

/* RFCOMM Parameter Negotiation - Retransmission Count */
#define RFCOMM_PN_RETRANSMISSION_COUNT          0x00

/* RFCOMM Remote Port Negotiation - Parameter Masks */
#define RFCOMM_PORT_MASK_BAUD_RATE              0x01
#define RFCOMM_PORT_MASK_DATA_BITS              0x02
#define RFCOMM_PORT_MASK_STOP_BIT               0x04
#define RFCOMM_PORT_MASK_PARITY                 0x08
#define RFCOMM_PORT_MASK_PARITY_TYPE            0x10
#define RFCOMM_PORT_MASK_X_ON                   0x20
#define RFCOMM_PORT_MASK_X_OFF                  0x40
#define RFCOMM_PORT_MASK_X_ON_X_OFF_INPUT       0x01
#define RFCOMM_PORT_MASK_X_ON_X_OFF_OUTPUT      0x02
#define RFCOMM_PORT_MASK_RTR_INPUT              0x04
#define RFCOMM_PORT_MASK_RTR_OUTPUT             0x08
#define RFCOMM_PORT_MASK_RTC_INPUT              0x10
#define RFCOMM_PORT_MASK_RTC_OUTPUT             0x20

/* RFCOMM Bit Masks for Various Packet Parameter Values */
#define RFCOMM_BIT_MASK_6_LSB                   0x3F
#define RFCOMM_BIT_MASK_4_LSB                   0x0F
#define RFCOMM_BIT_MASK_3_LSB                   0x07

/* RFCOMM Transmission & Reception Queue Types */
#define RFCOMM_TX_BUFFER                        0x01
#define RFCOMM_RX_BUFFER                        0x02

/* RFCOMM Tx/Rx Queue - Invalid Data Index */
#define RFCOMM_DATA_INVALID_INDEX               0xFFFF

/* Identifier for an Invalid DLCI */
#define RFCOMM_DLCI_INVALID                     RFCOMM_SESSION_DLCI

/* Minimum (2) Maximum Usable Value (61) for RFCOMM DLCIs */
#define RFCOMM_DLCI_MIN                         0x02
#define RFCOMM_DLCI_MAX                         0x3D

/* C/R Bit value for RFCOMM Multiplexer Command/Response */
#define RFCOMM_MUX_COMMAND_CR                   0x01
#define RFCOMM_MUX_RESPONSE_CR                  0x00

/*
 *  The default value for RPN Frame Value Octet X, containing
 *  default Data Bits, Stop Bit, Parity & Parity Type
 */
#define RFCOMM_DEFAULT_PORT_DATA_STOP_PARITY    0x03

/* Minimum & Maximum Frame Size in RFCOMM Parameter Negotiation (PN) */
#define RFCOMM_PN_FRAME_SIZE_MIN                23
#define RFCOMM_PN_FRAME_SIZE_MAX                32767

/* Initilizer for RFCOMM FCS Calculation */
#define RFCOMM_FCS_INIT_VALUE                   0xFF

/* FCS value to check received FCS - 11110011 (received order) */
#define RFCOMM_FCS_CHECK_VALUE                  0xCF


#ifdef RFCOMM_TEST_MODE
/* Definition for an Unsupported Command (for testing purpose only) */
#define RFCOMM_UNS_COMMAND                      0x34
#define RFCOMM_UNS_FRAME_SIZE                   2
#define RFCOMM_UNS_VALUE_SIZE                   0
#endif /* RFCOMM_TEST_MODE */


/* --------------------------------------------- Structures/Data Types */
/* The RFCOMM Session Entity */
typedef struct
{
    /* L2CAP Channel ID */
    UINT16  l2cap_cid;

    /* OutMTU Configured for the L2CAP Channel */
    UINT16  l2cap_out_mtu;

    /* L2CAP Channel Configuration State */
    UCHAR   l2cap_config;

    /* State of the RFCOMM Session (DLCI 0x00) */
    UCHAR   state;

    /* Boolean Flag to indicate Initiator of RFCOMM Session */
    UCHAR   initiator;

    /* Boolean Flag to indicate if Aggregare Flow Control Configured */
    UCHAR   fc;

    /*
     *  The use of Credit Based Flow Control is a 'Session' Characteristics.
     *  Use of CBFC gets established conclusively during the Parameter
     *  Negotiation before the first DLC establishment.
     *
     *  This Boolean Flag indicates if use of CBFC is configured for the
     *  RFCOMM Session.
     */
    UCHAR   use_credits;

    /* Number of Active DLCs on this RFCOMM Session */
    UCHAR   dlc_count;

#ifdef RFCOMM_USE_L2CAP_ERTM
    /* Flag to indicate if L2CAP transmission flow is off */
    UCHAR   flow;
#endif /* RFCOMM_USE_L2CAP_ERTM */

    /* Device Handle associated with the Remote Device for this RFCOMM Session */
    DEVICE_HANDLE   device_handle;

} RFCOMM_SESSION;



/* The RFCOMM DLCI Entity */
typedef struct
{
    /* The Notification Callback for Confirming RFCOMM Read & Write */
    RFCOMM_NOTIFY_CB notify_cb;

    /* Application (User) Buffer */
    UCHAR * ubuf;

#ifdef RFCOMM_ENABLE_USER_CXT_IN_HANDLE
    /*
     * Application provided User Context to be saved by RFCOMM and provided
     * through application callback.
     */
    void * blob;
#endif /* RFCOMM_ENABLE_USER_CXT_IN_HANDLE */

    /* Size of the Application (User) Buffer */
    UINT16  ubuf_len;

    /*
     *  This is a running counter which indicates how much of the
     *  original buffer already operated upon. For RFCOMM Write's,
     *  this holds the amount of data already transmitted to the
     *  peer.
     */
    UINT16  consumed;

    /* Local and Remote Credit Counters */
    UINT16  local_credit;
    UINT16  remote_credit;

    /* Frame Priority & Size (MTU) */
    UINT16  frame_size;

    /* DLCI Value */
    UCHAR   dlci;

    /* State of this RFCOMM DLCI */
    UCHAR   state;

    /* Index to RFCOMM Sessions that this DLCI belongs to */
    UCHAR   s_index;

    /* Index to RFCOMM Port Parameters Table */
    UCHAR   rpn_index;

    /* Transmission of Credit Enabled/Disabled */
    UCHAR   credit_tx;

    /* Local & Remore Modem Status Parameters */
    RFCOMM_MSC msc_local;
    RFCOMM_MSC msc_peer;

} RFCOMM_DLCI;



/* RFCOMM Remote Port Negotialtion Parameters for a DLCI */
typedef struct
{
    /* Buad Rate */
    UCHAR  baud_rate;

    /*
     *  Data Bits, Stop Bit, Parity and Partity Type
     *
     *   -----------------------------------------
     *  | D1 | D2 | S | P | PT1 | PT2 | Res | Res |
     *   -----------------------------------------
     *
     *  D1-D2   : Data Bits
     *  S       : Stop bit
     *  P       : Parity bit
     *  PT1-PT2 : Parity type
     *  Res     : (Reserved)
     */
    UCHAR  dspt;

    /* Flow Control (6 Bits) */
    UCHAR  flc;

    /* X-ON Character */
    UCHAR  x_on;

    /* X-OFF Character */
    UCHAR  x_off;

    /* DLCI Value */
    UCHAR  dlci;

} RFCOMM_PORT_PARAMS;



/* RFCOMM Application/User API/Command Context */
typedef struct
{
    /* Handle of the Timer associated with the Command */
    BT_timer_handle timer;

    /* Out/Return Parameters to the Application/User */
    void * uarea;

    /* Command Parameters */
    void * command_params;

    /* Length of the Out/Return Parameters to the Application/User */
    UINT16 uarea_len;

    /* 2-bytes padding */
    UINT16 dummy;

    /* RFCOMM Operation this Application/User Context belongs to */
    UCHAR operation;

    /* The RFCOMM Session Index for the API/Command */
    UCHAR s_index;

    /* The RFCOMM DLCI Value of the API/Command */
    UCHAR dlci;

    /* The Command Type */
    UCHAR command;

    /* RFCOMM Handle for the API/Command */
    RFCOMM_HANDLE handle;

} RFCOMM_CONTEXT;



/* RFCOMM Timer Object */
typedef struct
{
    /* RFCOMM DLCI Value */
    UCHAR dlci;

    /* Command Type for which the Timer is running */
    UCHAR command_type;

    /* BD_ADDR of the Remote Device, identifing RFCOMM Session */
    UCHAR bd_addr [BT_BD_ADDR_SIZE];

} RFCOMM_TIMER;




/* --------------------------------------------- BH Structures/Data Types */

/* RFCOMM Open Bottom Half Parameters */
typedef struct
{
    UCHAR            context_index;
    RFCOMM_HANDLE    handle;

} RFCOMM_OPEN_PARAMS;


/* RFCOMM Close Bottom Half Parameters */
typedef struct
{
    UCHAR            context_index;
    RFCOMM_HANDLE    handle;

} RFCOMM_CLOSE_PARAMS;


/* RFCOMM PN Bottom Half Parameters */
typedef struct
{
    UCHAR            context_index;
    RFCOMM_PN        pn;
    RFCOMM_HANDLE    handle;

} RFCOMM_PN_PARAMS;


/* RFCOMM MSC Bottom Half Parameters */
typedef struct
{
    UCHAR            context_index;
    RFCOMM_MSC       msc;
    RFCOMM_HANDLE    handle;

} RFCOMM_MSC_PARAMS;


/* RFCOMM RPN Bottom Half Parameters */
typedef struct
{
    RFCOMM_RPN *     rpn_rsp;
    UCHAR            context_index;
    RFCOMM_RPN       rpn;
    RFCOMM_HANDLE    handle;

} RFCOMM_RPN_PARAMS;


/* RFCOMM RLS Bottom Half Parameters */
typedef struct
{
    UCHAR            context_index;
    RFCOMM_RLS       rls;
    RFCOMM_HANDLE    handle;

} RFCOMM_RLS_PARAMS;


/* RFCOMM Write Bottom Half Parameters */
typedef struct
{
    UINT16 *         actual;
    UCHAR  *         ubuf;
    UINT16           ubuf_len;
    UCHAR            context_index;
    RFCOMM_HANDLE    handle;

} RFCOMM_WRITE_PARAMS;


/* RFCOMM Read Bottom Half Parameters */
typedef struct
{
    UINT16 *         actual;
    UCHAR  *         ubuf;
    UINT16           ubuf_len;
    UCHAR            context_index;
    RFCOMM_HANDLE    handle;

} RFCOMM_READ_PARAMS;


/* RFCOMM Test Bottom Half Parameters */
typedef struct
{
    UCHAR          context_index;
    UCHAR          bd_addr [BT_BD_ADDR_SIZE];
    RFCOMM_TEST    test;

} RFCOMM_TEST_PARAMS;


/* RFCOMM FC Bottom Half Parameters */
typedef struct
{
    UCHAR    context_index;
    UCHAR    frame_type;
    UCHAR    bd_addr [BT_BD_ADDR_SIZE];

} RFCOMM_FC_PARAMS;


/* RFCOMM Session Open Bottom Half Parameters */
typedef struct
{
    UCHAR    context_index;
    UCHAR    bd_addr [BT_BD_ADDR_SIZE];

} RFCOMM_SESSION_OPEN_PARAMS;


/* RFCOMM Session Close Bottom Half Parameters */
typedef struct
{
    UCHAR    context_index;
    UCHAR    bd_addr [BT_BD_ADDR_SIZE];

} RFCOMM_SESSION_CLOSE_PARAMS;


/* RFCOMM DLC Open Bottom Half Parameters */
typedef struct
{
    UCHAR            context_index;
    RFCOMM_HANDLE    handle;

} RFCOMM_DLC_OPEN_PARAMS;


/* RFCOMM DLC Close Bottom Half Parameters */
typedef struct
{
    UCHAR            context_index;
    RFCOMM_HANDLE    handle;

} RFCOMM_DLC_CLOSE_PARAMS;


#ifdef RFCOMM_CREDIT_TX_USE_BH
/* RFCOMM Creadit Tx Enable/Disable Bottom Half Parameters */
typedef struct
{
    UCHAR            flag;
    RFCOMM_HANDLE    handle;

} RFCOMM_CREDIT_TX_PARAMS;
#endif /* RFCOMM_CREDIT_TX_USE_BH */


/* --------------------------------------------- Macros */

/* RFCOMM Memory Allocation & Free */
#define rfcomm_malloc                   BT_alloc_mem
#define rfcomm_free                     BT_free_mem


/* Null Check for RFCOMM API Parameters */
#define RFCOMM_NULL_CHECK(x) \
        if (NULL == (x)) \
        { \
            RFCOMM_ERR( \
            "[RFCOMM] NULL Parameter Unacceptable in RFCOMM API\n"); \
            return RFCOMM_NULL_PARAMETER_NOT_ALLOWED; \
        }

/* Range Check for Server Channel in RFCOMM APIs */
#define RFCOMM_IS_VALID_SERVER_CHANNEL(sch) \
        if (((sch) < RFCOMM_SERVER_CHANNEL_MIN) || \
            ((sch) > RFCOMM_SERVER_CHANNEL_MAX)) \
        { \
            RFCOMM_ERR( \
            "[RFCOMM] Server Channel %d (0x%02X) Outside Range\n", \
            (sch), (sch)); \
            return RFCOMM_INVALID_SERVER_CHANNEL; \
        }

/* Rabge & Validity Check for Server Ch & DLCI pair in RFCOMM APIs */
#define RFCOMM_IS_VALID_SERVER_CHANNEL_DLCI(sch, dlc) \
        if (((sch) < RFCOMM_SERVER_CHANNEL_MIN) || \
            ((sch) > RFCOMM_SERVER_CHANNEL_MAX) || \
            ((sch) != rfcomm_get_server_channel((dlc)))) \
        { \
            RFCOMM_ERR( \
            "[RFCOMM] Check FAILED for Server Ch %d and DLCI 0x%02X\n", \
            (sch), (dlc)); \
            return RFCOMM_INVALID_SERVER_CHANNEL; \
        }

/*
 *  Locking RFCOMM Global Mutex
 *  (To be used in APIs/Callbacks/Functions returning 'API_RESULT')
 */
#define RFCOMM_MUTEX_LOCK()          BT_MUTEX_LOCK(rfcomm_mutex, RFCOMM)

/*
 *  Locking RFCOMM Global Mutex
 *  (To be used in BHs/Functions returning 'void')
 */
#define RFCOMM_MUTEX_LOCK_VOID()     BT_MUTEX_LOCK_VOID(rfcomm_mutex, RFCOMM)

/*
 *  Unlocking RFCOMM Global Mutex
 *  (To be used in APIs/Callbacks/Functions returning 'API_RESULT')
 */
#define RFCOMM_MUTEX_UNLOCK()        BT_MUTEX_UNLOCK(rfcomm_mutex, RFCOMM)

/*
 *  Unlocking RFCOMM Global Mutex
 *  (To be used in BHs/Functions returning 'void')
 */
#define RFCOMM_MUTEX_UNLOCK_VOID()   BT_MUTEX_UNLOCK_VOID(rfcomm_mutex, RFCOMM)


/* To Get RFCOMM DLCI Value from Server Channel */
#define rfcomm_get_dlci(dir, sch, dlc) \
        (dlc) = (((sch) << 1) | (!(dir))); \
        RFCOMM_TRC( \
        "[RFCOMM] Server Ch 0x%02X, Initiator 0x%02X => DLCI 0x%02X\n", \
        (sch), (dir), (dlc));

/* To Get RFCOMM Server Channel from DLCI Value */
#define rfcomm_get_server_channel(dlci)         (UCHAR)((dlci) >> 1)


/* To Reset RFCOMM Session */
#ifdef RFCOMM_USE_L2CAP_ERTM
#define rfcomm_reset_session(si) \
        rfcomm_session[(si)].state = RFCOMM_SESSION_INVALID; \
        DEVICE_HANDLE_INIT (rfcomm_session[(si)].device_handle); \
        rfcomm_session[(si)].initiator = 0x0; \
        rfcomm_session[(si)].l2cap_cid = RFCOMM_L2CAP_CID_NULL; \
        rfcomm_session[(si)].l2cap_out_mtu = 0; \
        rfcomm_session[(si)].l2cap_config = RFCOMM_L2CAP_CONFIG_NONE; \
        rfcomm_session[(si)].dlc_count = 0; \
        rfcomm_session[(si)].fc = RFCOMM_AGGREGATE_FLOW_ON; \
        rfcomm_session[(si)].flow = L2CAP_FEC_TX_FLOW_ON; \
        rfcomm_session[(si)].use_credits = RFCOMM_CBFC_DISABLED;
#else  /* RFCOMM_USE_L2CAP_ERTM */
#define rfcomm_reset_session(si) \
        rfcomm_session[(si)].state = RFCOMM_SESSION_INVALID; \
        DEVICE_HANDLE_INIT (rfcomm_session[(si)].device_handle); \
        rfcomm_session[(si)].initiator = 0x0; \
        rfcomm_session[(si)].l2cap_cid = RFCOMM_L2CAP_CID_NULL; \
        rfcomm_session[(si)].l2cap_out_mtu = 0; \
        rfcomm_session[(si)].l2cap_config = RFCOMM_L2CAP_CONFIG_NONE; \
        rfcomm_session[(si)].dlc_count = 0; \
        rfcomm_session[(si)].fc = RFCOMM_AGGREGATE_FLOW_ON; \
        rfcomm_session[(si)].use_credits = RFCOMM_CBFC_DISABLED;
#endif /* RFCOMM_USE_L2CAP_ERTM */

/* To Set Default RFCOMM Port Parameters */
#define rfcomm_set_default_port_params(indx) \
        rfcomm_rpn[indx].dlci = RFCOMM_DLCI_INVALID; \
        rfcomm_rpn[indx].baud_rate = RFCOMM_DEFAULT_PORT_BAUD_RATE; \
        rfcomm_rpn[indx].dspt = RFCOMM_DEFAULT_PORT_DATA_STOP_PARITY; \
        rfcomm_rpn[indx].flc = RFCOMM_DEFAULT_PORT_FLOW_CONTROL; \
        rfcomm_rpn[indx].x_on = RFCOMM_DEFAULT_PORT_XON_CHAR; \
        rfcomm_rpn[indx].x_off = RFCOMM_DEFAULT_PORT_XOFF_CHAR;


/* To print RPN Parameter values */
#ifdef RFCOMM_DEBUG

#define rfcomm_print_rpn(x) \
        RFCOMM_INF( \
        "Dumping RFCOMM RPN ...\n"); \
        RFCOMM_INF( \
        "  DLCI        = 0x%02X\n", (x)->dlci); \
        RFCOMM_INF( \
        "  Request     = 0x%02X\n", (x)->request); \
        RFCOMM_INF( \
        "  Baud Rate   = 0x%02X\n", (x)->baud_rate); \
        RFCOMM_INF( \
        "  Data Bits   = 0x%02X\n", (x)->data_bits); \
        RFCOMM_INF( \
        "  Stop Bit    = 0x%02X\n", (x)->stop_bit); \
        RFCOMM_INF( \
        "  Parity      = 0x%02X\n", (x)->parity); \
        RFCOMM_INF( \
        "  Parity Type = 0x%02X\n", (x)->parity); \
        RFCOMM_INF( \
        "  Flow Ctrl   = 0x%02X\n", (x)->flc); \
        RFCOMM_INF( \
        "  XON Char    = 0x%02X\n", (x)->x_on); \
        RFCOMM_INF( \
        "  XOFF Char   = 0x%02X\n", (x)->x_off); \
        RFCOMM_INF( \
        "  Mask Byte 1 = 0x%02X\n", (x)->mask[0]); \
        RFCOMM_INF( \
        "  Mask Byte 2 = 0x%02X\n", (x)->mask[1]);

#else  /* RFCOMM_DEBUG */

#define rfcomm_print_rpn(x)

#endif /* RFCOMM_DEBUG */

#ifdef RFCOMM_USE_L2CAP_ERTM
#ifdef RFCOMM_USE_L2CAP_ERTM_RUNTIME_CONFIG
/** Macro to set and get L2CAP Operation Mode */
#define RFCOMM_SET_L2CAP_OP_MODE(om) \
        rfcomm_l2cap_operation_mode = (om)

#define RFCOMM_GET_L2CAP_OP_MODE() \
        rfcomm_l2cap_operation_mode
#else
#define RFCOMM_SET_L2CAP_OP_MODE(om)
#define RFCOMM_GET_L2CAP_OP_MODE()   L2CAP_MODE_ERTM
#endif /* RFCOMM_USE_L2CAP_ERTM_RUNTIME_CONFIG */
#endif /* RFCOMM_USE_L2CAP_ERTM */

/* --------------------------------------------- Function Declarations */

/* RFCOMM API Handler */
API_RESULT rfcomm_common_api_handler
           (
               /* IN */  RFCOMM_HANDLE *    handle,
               /* IN */  UCHAR *            c_index,
               /* IN */  UCHAR              operation,
               /* IN */  void (* bh_handler)(void *, UINT16),
               /* IN */  void *             params,
               /* IN */  UINT16             params_len
           );


/* Calculation and Checking of RFCOMM FCS */
void rfcomm_calculate_fcs
     (
         /* IN */  UCHAR *    data,
         /* IN */  UINT16     datalen,
         /* OUT */ UCHAR *    fcs
     );

UCHAR rfcomm_check_fcs
      (
          /* IN */  UCHAR *    data,
          /* IN */  UCHAR      datalen,
          /* IN */  UCHAR      fcs_recvd
      );


/* L2CAP Callbacks */
API_RESULT rfcomm_l2ca_connect_ind
           (
               /* IN */  DEVICE_HANDLE    * handle,
               /* IN */  UINT16           lcid,
               /* IN */  UINT16           psm
           );

API_RESULT rfcomm_l2ca_connect_cnf
           (
               /* IN */  DEVICE_HANDLE    * handle,
               /* IN */  UINT16           lcid,
               /* IN */  UINT16           result,
               /* IN */  UINT16           status
           );

API_RESULT rfcomm_l2ca_disconnect_ind
           (
               /* IN */  UINT16    lcid
           );

API_RESULT rfcomm_l2ca_disconnect_cnf
           (
               /* IN */  UINT16    lcid,
               /* IN */  UINT16    result
           );

API_RESULT rfcomm_l2ca_config_ind
           (
               /* IN */  UINT16                   lcid,
               /* IN */  L2CAP_CONFIG_OPTION *    config_option
           );

API_RESULT rfcomm_l2ca_config_cnf
           (
               /* IN */  UINT16                   lcid,
               /* IN */  UINT16                   result,
               /* IN */  L2CAP_CONFIG_OPTION *    config_option
           );

API_RESULT rfcomm_l2ca_data_read_ind
           (
               /* IN */  UINT16     lcid,
               /* IN */  UCHAR *    data,
               /* IN */  UINT16     datalen
           );

#ifdef RFCOMM_USE_L2CAP_ERTM
API_RESULT rfcomm_l2ca_tx_flow_ind
           (
               /* IN */  UINT16   lcid,
               /* IN */  UCHAR    flow
           );

API_RESULT rfcomm_l2ca_get_fec_params
           (
               UINT16              lcid,
               L2CAP_FEC_OPTION    * fec_ptr
           );
#endif /* RFCOMM_USE_L2CAP_ERTM */

/* Handling of L2CAP Procedure/Operation Completion */
void rfcomm_l2cap_config_complete
     (
         /* IN */  UCHAR    s_index,
         /* IN */  UCHAR    state
     );



/* To send RFCOMM Mode Setting Commands & Responses */
API_RESULT rfcomm_send_mode_frame
           (
               /* IN */  UCHAR    s_index,
               /* IN */  UCHAR    dlci,
               /* IN */  UCHAR    frame_type
           );

API_RESULT rfcomm_send_mode_command
           (
               /* IN */  UCHAR    s_index,
               /* IN */  UCHAR    c_index,
               /* IN */  UCHAR    dlci,
               /* IN */  UCHAR    frame_type
           );


/* To send RFCOMM Multiplexer Command/Response Frame */
API_RESULT rfcomm_send_mux_frame
           (
               /* IN */  UCHAR     s_index,
               /* IN */  UCHAR     cr_bit,
               /* IN */  UCHAR     mux_frame,
               /* IN */  UCHAR     mux_length,
               /* IN */  void *    mux_args
           );

API_RESULT rfcomm_send_mux_command
           (
               /* IN */  UCHAR     dlci,
               /* IN */  UCHAR     mux_type,
               /* IN */  void *    mux_frame,
               /* IN */  UCHAR     s_index,
               /* IN */  UCHAR     c_index
           );


/* To send UIH Frame */
API_RESULT rfcomm_send_uih
           (
               /* IN */  UCHAR      s_index,
               /* IN */  UCHAR      dlci,
               /* IN */  UCHAR      uih_p_bit,
               /* IN */  UCHAR *    frame,
               /* IN */  UINT16     payload_len,
               /* OUT */ UINT16 *   len_written
           );


/* RFCOMM Command (Mode & Mux) Timeout Handler */
void rfcomm_command_timeout
     (
         /* IN */  void *    args,
         /* IN */  UINT16    args_len
     );



/* RFCOMM Incoming Mode Setting Command/Response Handlers */
void rfcomm_handle_sabm_with_sm
     (
         /* IN */  UCHAR    s_index,
         /* IN */  UCHAR    dlci,
         /* IN */  UCHAR    dlci_index
     );

void rfcomm_handle_sabm
     (
         /* IN */  UCHAR    s_index,
         /* IN */  UCHAR    dlci,
         /* IN */  UCHAR    dlci_index
     );

void rfcomm_handle_disc
     (
         /* IN */  UCHAR    s_index,
         /* IN */  UCHAR    dlci,
         /* IN */  UCHAR    dlci_index
     );

void rfcomm_handle_ua
     (
         /* IN */  UCHAR    s_index,
         /* IN */  UCHAR    dlci,
         /* IN */  UCHAR    dlci_index
     );

void rfcomm_handle_dm
     (
         /* IN */  UCHAR    s_index,
         /* IN */  UCHAR    dlci,
         /* IN */  UCHAR    dlci_index
     );

void rfcomm_sabm_command_complete
     (
         /* IN */  UCHAR    s_index,
         /* IN */  UCHAR    context_index,
         /* IN */  UCHAR    dlci_index,
         /* IN */  UCHAR    dlci
     );

void rfcomm_disc_command_complete
     (
         /* IN */  UCHAR    s_index,
         /* IN */  UCHAR    context_index,
         /* IN */  UCHAR    dlci_index,
         /* IN */  UCHAR    dlci
     );


/* RFCOMM Incoming Multiplexer Command/Response Handlers */
void rfcomm_handle_pn
     (
         /* IN */  UCHAR      s_index,
         /* IN */  UCHAR      cr,
         /* IN */  UCHAR *    data,
         /* IN */  UINT16     datalen
     );

void rfcomm_handle_msc
     (
         /* IN */  UCHAR      s_index,
         /* IN */  UCHAR      cr,
         /* IN */  UCHAR *    data,
         /* IN */  UINT16     datalen
     );

void rfcomm_handle_rpn
     (
         /* IN */  UCHAR      s_index,
         /* IN */  UCHAR      cr,
         /* IN */  UCHAR *    data,
         /* IN */  UINT16     datalen
     );

void rfcomm_handle_rls
     (
         /* IN */  UCHAR      s_index,
         /* IN */  UCHAR      cr,
         /* IN */  UCHAR *    data,
         /* IN */  UINT16     datalen
     );

void rfcomm_handle_fc_on
     (
         /* IN */  UCHAR      s_index,
         /* IN */  UCHAR      cr,
         /* IN */  UCHAR *    data,
         /* IN */  UINT16     datalen
     );

void rfcomm_handle_fc_off
     (
         /* IN */  UCHAR      s_index,
         /* IN */  UCHAR      cr,
         /* IN */  UCHAR *    data,
         /* IN */  UINT16     datalen
     );

void rfcomm_handle_nsc
     (
         /* IN */  UCHAR      s_index,
         /* IN */  UCHAR      cr,
         /* IN */  UCHAR *    data,
         /* IN */  UINT16     datalen
     );

void rfcomm_handle_test
     (
         /* IN */  UCHAR      s_index,
         /* IN */  UCHAR      cr,
         /* IN */  UCHAR *    data,
         /* IN */  UINT16     datalen
     );


/* To Create a RFCOMM Session */
API_RESULT rfcomm_session_open
           (
               /* IN */  UCHAR *    bd_addr,
               /* IN */  UCHAR      context_index,
               /* OUT */ UCHAR *    s_index
           );


/* To Transmit RFCOMM Application/User Data from Tx Queue */
void rfcomm_transmit_data
     (
         /* IN */  UCHAR    s_index,
         /* IN */  UCHAR    dlci_index
     );


/* To Send RFCOMM Local Credits to Peer */
void rfcomm_send_credits
     (
         /* IN */  UCHAR    s_index,
         /* IN */  UCHAR    dlci_index
     );


/* To Set/Get Local RPN Parameters */
void rfcomm_set_local_rpn
     (
         /* IN */  UCHAR           dlci_index,
         /* IN */  RFCOMM_RPN *    rpn_req
     );

void rfcomm_get_local_rpn
     (
         /* IN */  UCHAR           dlci_index,
         /* OUT */ RFCOMM_RPN *    rpn_req
     );

void rfcomm_copy_changed_port_settings
     (
         /* IN */  RFCOMM_RPN *    rpn_src,
         /* OUT */ RFCOMM_RPN *    rpn_dest
     );

void rfcomm_copy_accepted_port_settings
     (
         /* IN */  RFCOMM_RPN *    rpn_src,
         /* OUT */ RFCOMM_RPN *    rpn_dest
     );


/* RFCOMM Session Entity Management */
UCHAR rfcomm_add_session
      (
          /* IN */  DEVICE_HANDLE    * handle
      );

UCHAR rfcomm_get_session_bd_addr
      (
          /* IN */  UCHAR            * bd_addr,
          /* IN */  DEVICE_HANDLE    handle
      );

UCHAR rfcomm_get_session_lcid
      (
          /* IN */  UINT16     lcid
      );

void rfcomm_del_session
     (
         /* IN */ UCHAR     s_index,
         /* IN */ UINT16    reason
     );


/* RFCOMM DLCI Entity Management */
UCHAR rfcomm_add_dlci
      (
          /* IN */  UCHAR      s_index,
          /* IN */  UCHAR      dlci
      );

UCHAR rfcomm_search_dlci
      (
          /* IN */  UCHAR      s_index,
          /* IN */  UCHAR      dlci
      );

void rfcomm_reset_dlci_params
     (
         /* IN */  UCHAR    dlci_index
     );

void rfcomm_reset_dlci
     (
         /* IN */  UCHAR     dlci_index,
         /* IN */  UINT16    reason
     );


/* RFCOMM Context Entity Management */
UCHAR rfcomm_search_accept
      (
          /* IN */  UCHAR    server_channel
      );

void rfcomm_free_context
      (
          /* IN */  UCHAR    c_index
      );

void rfcomm_context_signal
      (
          /* IN */  UCHAR    c_index,
          /* IN */  UINT16   result
      );

UCHAR rfcomm_search_command
      (
          /* IN */ UCHAR    s_index,
          /* IN */ UCHAR    command_type,
          /* IN */ UCHAR    dlci,
          /* IN */ UCHAR    stop_timer
      );


#ifdef RFCOMM_TEST_MODE_MALLOC
void * rfcomm_malloc_data (UINT16 size);
#endif /* RFCOMM_TEST_MODE_MALLOC */

void rfcomm_get_bd_addr (UCHAR s_index, UCHAR * bd_addr);

API_RESULT rfcomm_get_device_queue_handle
           (
               /* IN */ UCHAR            * bd_addr,
               /* IN */ DEVICE_HANDLE    * handle
           );

#endif /* _H_RFCOMM_INTERNAL_ */


